home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / net_main.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  20KB  |  998 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // net_main.c
  21.  
  22. #include "quakedef.h"
  23. #include "net_vcr.h"
  24.  
  25. qsocket_t    *net_activeSockets = NULL;
  26. qsocket_t    *net_freeSockets = NULL;
  27. int            net_numsockets = 0;
  28.  
  29. qboolean    serialAvailable = false;
  30. qboolean    ipxAvailable = false;
  31. qboolean    tcpipAvailable = false;
  32.  
  33. int            net_hostport;
  34. int            DEFAULTnet_hostport = 26000;
  35.  
  36. char        my_ipx_address[NET_NAMELEN];
  37. char        my_tcpip_address[NET_NAMELEN];
  38.  
  39. void (*GetComPortConfig) (int portNumber, int *port, int *irq, int *baud, qboolean *useModem);
  40. void (*SetComPortConfig) (int portNumber, int port, int irq, int baud, qboolean useModem);
  41. void (*GetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
  42. void (*SetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
  43.  
  44. static qboolean    listening = false;
  45.  
  46. qboolean    slistInProgress = false;
  47. qboolean    slistSilent = false;
  48. qboolean    slistLocal = true;
  49. static double    slistStartTime;
  50. static int        slistLastShown;
  51.  
  52. static void Slist_Send(void);
  53. static void Slist_Poll(void);
  54. PollProcedure    slistSendProcedure = {NULL, 0.0, Slist_Send};
  55. PollProcedure    slistPollProcedure = {NULL, 0.0, Slist_Poll};
  56.  
  57.  
  58. sizebuf_t        net_message;
  59. int                net_activeconnections = 0;
  60.  
  61. int messagesSent = 0;
  62. int messagesReceived = 0;
  63. int unreliableMessagesSent = 0;
  64. int unreliableMessagesReceived = 0;
  65.  
  66. cvar_t    net_messagetimeout = {"net_messagetimeout","300"};
  67. cvar_t    hostname = {"hostname", "UNNAMED"};
  68.  
  69. qboolean    configRestored = false;
  70. cvar_t    config_com_port = {"_config_com_port", "0x3f8", true};
  71. cvar_t    config_com_irq = {"_config_com_irq", "4", true};
  72. cvar_t    config_com_baud = {"_config_com_baud", "57600", true};
  73. cvar_t    config_com_modem = {"_config_com_modem", "1", true};
  74. cvar_t    config_modem_dialtype = {"_config_modem_dialtype", "T", true};
  75. cvar_t    config_modem_clear = {"_config_modem_clear", "ATZ", true};
  76. cvar_t    config_modem_init = {"_config_modem_init", "", true};
  77. cvar_t    config_modem_hangup = {"_config_modem_hangup", "AT H", true};
  78.  
  79. #ifdef IDGODS
  80. cvar_t    idgods = {"idgods", "0"};
  81. #endif
  82.  
  83. int    vcrFile = -1;
  84. qboolean recording = false;
  85.  
  86. // these two macros are to make the code more readable
  87. #define sfunc    net_drivers[sock->driver]
  88. #define dfunc    net_drivers[net_driverlevel]
  89.  
  90. int    net_driverlevel;
  91.  
  92.  
  93. double            net_time;
  94.  
  95. double SetNetTime(void)
  96. {
  97.     net_time = Sys_FloatTime();
  98.     return net_time;
  99. }
  100.  
  101.  
  102. /*
  103. ===================
  104. NET_NewQSocket
  105.  
  106. Called by drivers when a new communications endpoint is required
  107. The sequence and buffer fields will be filled in properly
  108. ===================
  109. */
  110. qsocket_t *NET_NewQSocket (void)
  111. {
  112.     qsocket_t    *sock;
  113.  
  114.     if (net_freeSockets == NULL)
  115.         return NULL;
  116.  
  117.     if (net_activeconnections >= svs.maxclients)
  118.         return NULL;
  119.  
  120.     // get one from free list
  121.     sock = net_freeSockets;
  122.     net_freeSockets = sock->next;
  123.  
  124.     // add it to active list
  125.     sock->next = net_activeSockets;
  126.     net_activeSockets = sock;
  127.  
  128.     sock->disconnected = false;
  129.     sock->connecttime = net_time;
  130.     Q_strcpy (sock->address,"UNSET ADDRESS");
  131.     sock->driver = net_driverlevel;
  132.     sock->socket = 0;
  133.     sock->driverdata = NULL;
  134.     sock->canSend = true;
  135.     sock->sendNext = false;
  136.     sock->lastMessageTime = net_time;
  137.     sock->ackSequence = 0;
  138.     sock->sendSequence = 0;
  139.     sock->unreliableSendSequence = 0;
  140.     sock->sendMessageLength = 0;
  141.     sock->receiveSequence = 0;
  142.     sock->unreliableReceiveSequence = 0;
  143.     sock->receiveMessageLength = 0;
  144.  
  145.     return sock;
  146. }
  147.  
  148.  
  149. void NET_FreeQSocket(qsocket_t *sock)
  150. {
  151.     qsocket_t    *s;
  152.  
  153.     // remove it from active list
  154.     if (sock == net_activeSockets)
  155.         net_activeSockets = net_activeSockets->next;
  156.     else
  157.     {
  158.         for (s = net_activeSockets; s; s = s->next)
  159.             if (s->next == sock)
  160.             {
  161.                 s->next = sock->next;
  162.                 break;
  163.             }
  164.         if (!s)
  165.             Sys_Error ("NET_FreeQSocket: not active\n");
  166.     }
  167.  
  168.     // add it to free list
  169.     sock->next = net_freeSockets;
  170.     net_freeSockets = sock;
  171.     sock->disconnected = true;
  172. }
  173.  
  174.  
  175. static void NET_Listen_f (void)
  176. {
  177.     if (Cmd_Argc () != 2)
  178.     {
  179.         Con_Printf ("\"listen\" is \"%u\"\n", listening ? 1 : 0);
  180.         return;
  181.     }
  182.  
  183.     listening = Q_atoi(Cmd_Argv(1)) ? true : false;
  184.  
  185.     for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
  186.     {
  187.         if (net_drivers[net_driverlevel].initialized == false)
  188.             continue;
  189.         dfunc.Listen (listening);
  190.     }
  191. }
  192.  
  193.  
  194. static void MaxPlayers_f (void)
  195. {
  196.     int     n;
  197.  
  198.     if (Cmd_Argc () != 2)
  199.     {
  200.         Con_Printf ("\"maxplayers\" is \"%u\"\n", svs.maxclients);
  201.         return;
  202.     }
  203.  
  204.     if (sv.active)
  205.     {
  206.         Con_Printf ("maxplayers can not be changed while a server is running.\n");
  207.         return;
  208.     }
  209.  
  210.     n = Q_atoi(Cmd_Argv(1));
  211.     if (n < 1)
  212.         n = 1;
  213.     if (n > svs.maxclientslimit)
  214.     {
  215.         n = svs.maxclientslimit;
  216.         Con_Printf ("\"maxplayers\" set to \"%u\"\n", n);
  217.     }
  218.  
  219.     if ((n == 1) && listening)
  220.         Cbuf_AddText ("listen 0\n");
  221.  
  222.     if ((n > 1) && (!listening))
  223.         Cbuf_AddText ("listen 1\n");
  224.  
  225.     svs.maxclients = n;
  226.     if (n == 1)
  227.         Cvar_Set ("deathmatch", "0");
  228.     else
  229.         Cvar_Set ("deathmatch", "1");
  230. }
  231.  
  232.  
  233. static void NET_Port_f (void)
  234. {
  235.     int     n;
  236.  
  237.     if (Cmd_Argc () != 2)
  238.     {
  239.         Con_Printf ("\"port\" is \"%u\"\n", net_hostport);
  240.         return;
  241.     }
  242.  
  243.     n = Q_atoi(Cmd_Argv(1));
  244.     if (n < 1 || n > 65534)
  245.     {
  246.         Con_Printf ("Bad value, must be between 1 and 65534\n");
  247.         return;
  248.     }
  249.  
  250.     DEFAULTnet_hostport = n;
  251.     net_hostport = n;
  252.  
  253.     if (listening)
  254.     {
  255.         // force a change to the new port
  256.         Cbuf_AddText ("listen 0\n");
  257.         Cbuf_AddText ("listen 1\n");
  258.     }
  259. }
  260.  
  261.  
  262. static void PrintSlistHeader(void)
  263. {
  264.     Con_Printf("Server          Map             Users\n");
  265.     Con_Printf("--------------- --------------- -----\n");
  266.     slistLastShown = 0;
  267. }
  268.  
  269.  
  270. static void PrintSlist(void)
  271. {
  272.     int n;
  273.  
  274.     for (n = slistLastShown; n < hostCacheCount; n++)
  275.     {
  276.         if (hostcache[n].maxusers)
  277.             Con_Printf("%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers);
  278.         else
  279.             Con_Printf("%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map);
  280.     }
  281.     slistLastShown = n;
  282. }
  283.  
  284.  
  285. static void PrintSlistTrailer(void)
  286. {
  287.     if (hostCacheCount)
  288.         Con_Printf("== end list ==\n\n");
  289.     else
  290.         Con_Printf("No Quake servers found.\n\n");
  291. }
  292.  
  293.  
  294. void NET_Slist_f (void)
  295. {
  296.     if (slistInProgress)
  297.         return;
  298.  
  299.     if (! slistSilent)
  300.     {
  301.         Con_Printf("Looking for Quake servers...\n");
  302.         PrintSlistHeader();
  303.     }
  304.  
  305.     slistInProgress = true;
  306.     slistStartTime = Sys_FloatTime();
  307.  
  308.     SchedulePollProcedure(&slistSendProcedure, 0.0);
  309.     SchedulePollProcedure(&slistPollProcedure, 0.1);
  310.  
  311.     hostCacheCount = 0;
  312. }
  313.  
  314.  
  315. static void Slist_Send(void)
  316. {
  317.     for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
  318.     {
  319.         if (!slistLocal && net_driverlevel == 0)
  320.             continue;
  321.         if (net_drivers[net_driverlevel].initialized == false)
  322.             continue;
  323.         dfunc.SearchForHosts (true);
  324.     }
  325.  
  326.     if ((Sys_FloatTime() - slistStartTime) < 0.5)
  327.         SchedulePollProcedure(&slistSendProcedure, 0.75);
  328. }
  329.  
  330.  
  331. static void Slist_Poll(void)
  332. {
  333.     for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
  334.     {
  335.         if (!slistLocal && net_driverlevel == 0)
  336.             continue;
  337.         if (net_drivers[net_driverlevel].initialized == false)
  338.             continue;
  339.         dfunc.SearchForHosts (false);
  340.     }
  341.  
  342.     if (! slistSilent)
  343.         PrintSlist();
  344.  
  345.     if ((Sys_FloatTime() - slistStartTime) < 1.5)
  346.     {
  347.         SchedulePollProcedure(&slistPollProcedure, 0.1);
  348.         return;
  349.     }
  350.  
  351.     if (! slistSilent)
  352.         PrintSlistTrailer();
  353.     slistInProgress = false;
  354.     slistSilent = false;
  355.     slistLocal = true;
  356. }
  357.  
  358.  
  359. /*
  360. ===================
  361. NET_Connect
  362. ===================
  363. */
  364.  
  365. int hostCacheCount = 0;
  366. hostcache_t hostcache[HOSTCACHESIZE];
  367.  
  368. qsocket_t *NET_Connect (char *host)
  369. {
  370.     qsocket_t        *ret;
  371.     int                n;
  372.     int                numdrivers = net_numdrivers;
  373.  
  374.     SetNetTime();
  375.  
  376.     if (host && *host == 0)
  377.         host = NULL;
  378.  
  379.     if (host)
  380.     {
  381.         if (Q_strcasecmp (host, "local") == 0)
  382.         {
  383.             numdrivers = 1;
  384.             goto JustDoIt;
  385.         }
  386.  
  387.         if (hostCacheCount)
  388.         {
  389.             for (n = 0; n < hostCacheCount; n++)
  390.                 if (Q_strcasecmp (host, hostcache[n].name) == 0)
  391.                 {
  392.                     host = hostcache[n].cname;
  393.                     break;
  394.                 }
  395.             if (n < hostCacheCount)
  396.                 goto JustDoIt;
  397.         }
  398.     }
  399.  
  400.     slistSilent = host ? true : false;
  401.     NET_Slist_f ();
  402.  
  403.     while(slistInProgress)
  404.         NET_Poll();
  405.  
  406.     if (host == NULL)
  407.     {
  408.         if (hostCacheCount != 1)
  409.             return NULL;
  410.         host = hostcache[0].cname;
  411.         Con_Printf("Connecting to...\n%s @ %s\n\n", hostcache[0].name, host);
  412.     }
  413.  
  414.     if (hostCacheCount)
  415.         for (n = 0; n < hostCacheCount; n++)
  416.             if (Q_strcasecmp (host, hostcache[n].name) == 0)
  417.             {
  418.                 host = hostcache[n].cname;
  419.                 break;
  420.             }
  421.  
  422. JustDoIt:
  423.     for (net_driverlevel=0 ; net_driverlevel<numdrivers; net_driverlevel++)
  424.     {
  425.         if (net_drivers[net_driverlevel].initialized == false)
  426.             continue;
  427.         ret = dfunc.Connect (host);
  428.         if (ret)
  429.             return ret;
  430.     }
  431.  
  432.     if (host)
  433.     {
  434.         Con_Printf("\n");
  435.         PrintSlistHeader();
  436.         PrintSlist();
  437.         PrintSlistTrailer();
  438.     }
  439.     
  440.     return NULL;
  441. }
  442.  
  443.  
  444. /*
  445. ===================
  446. NET_CheckNewConnections
  447. ===================
  448. */
  449.  
  450. struct
  451. {
  452.     double    time;
  453.     int        op;
  454.     long    session;
  455. } vcrConnect;
  456.  
  457. qsocket_t *NET_CheckNewConnections (void)
  458. {
  459.     qsocket_t    *ret;
  460.  
  461.     SetNetTime();
  462.  
  463.     for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
  464.     {
  465.         if (net_drivers[net_driverlevel].initialized == false)
  466.             continue;
  467.         if (net_driverlevel && listening == false)
  468.             continue;
  469.         ret = dfunc.CheckNewConnections ();
  470.         if (ret)
  471.         {
  472.             if (recording)
  473.             {
  474.                 vcrConnect.time = host_time;
  475.                 vcrConnect.op = VCR_OP_CONNECT;
  476.                 vcrConnect.session = (long)ret;
  477.                 Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect));
  478.                 Sys_FileWrite (vcrFile, ret->address, NET_NAMELEN);
  479.             }
  480.             return ret;
  481.         }
  482.     }
  483.     
  484.     if (recording)
  485.     {
  486.         vcrConnect.time = host_time;
  487.         vcrConnect.op = VCR_OP_CONNECT;
  488.         vcrConnect.session = 0;
  489.         Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect));
  490.     }
  491.  
  492.     return NULL;
  493. }
  494.  
  495. /*
  496. ===================
  497. NET_Close
  498. ===================
  499. */
  500. void NET_Close (qsocket_t *sock)
  501. {
  502.     if (!sock)
  503.         return;
  504.  
  505.     if (sock->disconnected)
  506.         return;
  507.  
  508.     SetNetTime();
  509.  
  510.     // call the driver_Close function
  511.     sfunc.Close (sock);
  512.  
  513.     NET_FreeQSocket(sock);
  514. }
  515.  
  516.  
  517. /*
  518. =================
  519. NET_GetMessage
  520.  
  521. If there is a complete message, return it in net_message
  522.  
  523. returns 0 if no data is waiting
  524. returns 1 if a message was received
  525. returns -1 if connection is invalid
  526. =================
  527. */
  528.  
  529. struct
  530. {
  531.     double    time;
  532.     int        op;
  533.     long    session;
  534.     int        ret;
  535.     int        len;
  536. } vcrGetMessage;
  537.  
  538. extern void PrintStats(qsocket_t *s);
  539.  
  540. int    NET_GetMessage (qsocket_t *sock)
  541. {
  542.     int ret;
  543.  
  544.     if (!sock)
  545.         return -1;
  546.  
  547.     if (sock->disconnected)
  548.     {
  549.         Con_Printf("NET_GetMessage: disconnected socket\n");
  550.         return -1;
  551.     }
  552.  
  553.     SetNetTime();
  554.  
  555.     ret = sfunc.QGetMessage(sock);
  556.  
  557.     // see if this connection has timed out
  558.     if (ret == 0 && sock->driver)
  559.     {
  560.         if (net_time - sock->lastMessageTime > net_messagetimeout.value)
  561.         {
  562.             NET_Close(sock);
  563.             return -1;
  564.         }
  565.     }
  566.  
  567.  
  568.     if (ret > 0)
  569.     {
  570.         if (sock->driver)
  571.         {
  572.             sock->lastMessageTime = net_time;
  573.             if (ret == 1)
  574.                 messagesReceived++;
  575.             else if (ret == 2)
  576.                 unreliableMessagesReceived++;
  577.         }
  578.  
  579.         if (recording)
  580.         {
  581.             vcrGetMessage.time = host_time;
  582.             vcrGetMessage.op = VCR_OP_GETMESSAGE;
  583.             vcrGetMessage.session = (long)sock;
  584.             vcrGetMessage.ret = ret;
  585.             vcrGetMessage.len = net_message.cursize;
  586.             Sys_FileWrite (vcrFile, &vcrGetMessage, 24);
  587.             Sys_FileWrite (vcrFile, net_message.data, net_message.cursize);
  588.         }
  589.     }
  590.     else
  591.     {
  592.         if (recording)
  593.         {
  594.             vcrGetMessage.time = host_time;
  595.             vcrGetMessage.op = VCR_OP_GETMESSAGE;
  596.             vcrGetMessage.session = (long)sock;
  597.             vcrGetMessage.ret = ret;
  598.             Sys_FileWrite (vcrFile, &vcrGetMessage, 20);
  599.         }
  600.     }
  601.  
  602.     return ret;
  603. }
  604.  
  605.  
  606. /*
  607. ==================
  608. NET_SendMessage
  609.  
  610. Try to send a complete length+message unit over the reliable stream.
  611. returns 0 if the message cannot be delivered reliably, but the connection
  612.         is still considered valid
  613. returns 1 if the message was sent properly
  614. returns -1 if the connection died
  615. ==================
  616. */
  617. struct
  618. {
  619.     double    time;
  620.     int        op;
  621.     long    session;
  622.     int        r;
  623. } vcrSendMessage;
  624.  
  625. int NET_SendMessage (qsocket_t *sock, sizebuf_t *data)
  626. {
  627.     int        r;
  628.     
  629.     if (!sock)
  630.         return -1;
  631.  
  632.     if (sock->disconnected)
  633.     {
  634.         Con_Printf("NET_SendMessage: disconnected socket\n");
  635.         return -1;
  636.     }
  637.  
  638.     SetNetTime();
  639.     r = sfunc.QSendMessage(sock, data);
  640.     if (r == 1 && sock->driver)
  641.         messagesSent++;
  642.  
  643.     if (recording)
  644.     {
  645.         vcrSendMessage.time = host_time;
  646.         vcrSendMessage.op = VCR_OP_SENDMESSAGE;
  647.         vcrSendMessage.session = (long)sock;
  648.         vcrSendMessage.r = r;
  649.         Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
  650.     }
  651.     
  652.     return r;
  653. }
  654.  
  655.  
  656. int NET_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
  657. {
  658.     int        r;
  659.     
  660.     if (!sock)
  661.         return -1;
  662.  
  663.     if (sock->disconnected)
  664.     {
  665.         Con_Printf("NET_SendMessage: disconnected socket\n");
  666.         return -1;
  667.     }
  668.  
  669.     SetNetTime();
  670.     r = sfunc.SendUnreliableMessage(sock, data);
  671.     if (r == 1 && sock->driver)
  672.         unreliableMessagesSent++;
  673.  
  674.     if (recording)
  675.     {
  676.         vcrSendMessage.time = host_time;
  677.         vcrSendMessage.op = VCR_OP_SENDMESSAGE;
  678.         vcrSendMessage.session = (long)sock;
  679.         vcrSendMessage.r = r;
  680.         Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
  681.     }
  682.     
  683.     return r;
  684. }
  685.  
  686.  
  687. /*
  688. ==================
  689. NET_CanSendMessage
  690.  
  691. Returns true or false if the given qsocket can currently accept a
  692. message to be transmitted.
  693. ==================
  694. */
  695. qboolean NET_CanSendMessage (qsocket_t *sock)
  696. {
  697.     int        r;
  698.     
  699.     if (!sock)
  700.         return false;
  701.  
  702.     if (sock->disconnected)
  703.         return false;
  704.  
  705.     SetNetTime();
  706.  
  707.     r = sfunc.CanSendMessage(sock);
  708.     
  709.     if (recording)
  710.     {
  711.         vcrSendMessage.time = host_time;
  712.         vcrSendMessage.op = VCR_OP_CANSENDMESSAGE;
  713.         vcrSendMessage.session = (long)sock;
  714.         vcrSendMessage.r = r;
  715.         Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
  716.     }
  717.     
  718.     return r;
  719. }
  720.  
  721.  
  722. int NET_SendToAll(sizebuf_t *data, int blocktime)
  723. {
  724.     double        start;
  725.     int            i;
  726.     int            count = 0;
  727.     qboolean    state1 [MAX_SCOREBOARD];
  728.     qboolean    state2 [MAX_SCOREBOARD];
  729.  
  730.     for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
  731.     {
  732.         if (!host_client->netconnection)
  733.             continue;
  734.         if (host_client->active)
  735.         {
  736.             if (host_client->netconnection->driver == 0)
  737.             {
  738.                 NET_SendMessage(host_client->netconnection, data);
  739.                 state1[i] = true;
  740.                 state2[i] = true;
  741.                 continue;
  742.             }
  743.             count++;
  744.             state1[i] = false;
  745.             state2[i] = false;
  746.         }
  747.         else
  748.         {
  749.             state1[i] = true;
  750.             state2[i] = true;
  751.         }
  752.     }
  753.  
  754.     start = Sys_FloatTime();
  755.     while (count)
  756.     {
  757.         count = 0;
  758.         for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
  759.         {
  760.             if (! state1[i])
  761.             {
  762.                 if (NET_CanSendMessage (host_client->netconnection))
  763.                 {
  764.                     state1[i] = true;
  765.                     NET_SendMessage(host_client->netconnection, data);
  766.                 }
  767.                 else
  768.                 {
  769.                     NET_GetMessage (host_client->netconnection);
  770.                 }
  771.                 count++;
  772.                 continue;
  773.             }
  774.  
  775.             if (! state2[i])
  776.             {
  777.                 if (NET_CanSendMessage (host_client->netconnection))
  778.                 {
  779.                     state2[i] = true;
  780.                 }
  781.                 else
  782.                 {
  783.                     NET_GetMessage (host_client->netconnection);
  784.                 }
  785.                 count++;
  786.                 continue;
  787.             }
  788.         }
  789.         if ((Sys_FloatTime() - start) > blocktime)
  790.             break;
  791.     }
  792.     return count;
  793. }
  794.  
  795.  
  796. //=============================================================================
  797.  
  798. /*
  799. ====================
  800. NET_Init
  801. ====================
  802. */
  803.  
  804. void NET_Init (void)
  805. {
  806.     int            i;
  807.     int            controlSocket;
  808.     qsocket_t    *s;
  809.  
  810.     if (COM_CheckParm("-playback"))
  811.     {
  812.         net_numdrivers = 1;
  813.         net_drivers[0].Init = VCR_Init;
  814.     }
  815.  
  816.     if (COM_CheckParm("-record"))
  817.         recording = true;
  818.  
  819.     i = COM_CheckParm ("-port");
  820.     if (!i)
  821.         i = COM_CheckParm ("-udpport");
  822.     if (!i)
  823.         i = COM_CheckParm ("-ipxport");
  824.  
  825.     if (i)
  826.     {
  827.         if (i < com_argc-1)
  828.             DEFAULTnet_hostport = Q_atoi (com_argv[i+1]);
  829.         else
  830.             Sys_Error ("NET_Init: you must specify a number after -port");
  831.     }
  832.     net_hostport = DEFAULTnet_hostport;
  833.  
  834.     if (COM_CheckParm("-listen") || cls.state == ca_dedicated)
  835.         listening = true;
  836.     net_numsockets = svs.maxclientslimit;
  837.     if (cls.state != ca_dedicated)
  838.         net_numsockets++;
  839.  
  840.     SetNetTime();
  841.  
  842.     for (i = 0; i < net_numsockets; i++)
  843.     {
  844.         s = (qsocket_t *)Hunk_AllocName(sizeof(qsocket_t), "qsocket");
  845.         s->next = net_freeSockets;
  846.         net_freeSockets = s;
  847.         s->disconnected = true;
  848.     }
  849.  
  850.     // allocate space for network message buffer
  851.     SZ_Alloc (&net_message, NET_MAXMESSAGE);
  852.  
  853.     Cvar_RegisterVariable (&net_messagetimeout);
  854.     Cvar_RegisterVariable (&hostname);
  855.     Cvar_RegisterVariable (&config_com_port);
  856.     Cvar_RegisterVariable (&config_com_irq);
  857.     Cvar_RegisterVariable (&config_com_baud);
  858.     Cvar_RegisterVariable (&config_com_modem);
  859.     Cvar_RegisterVariable (&config_modem_dialtype);
  860.     Cvar_RegisterVariable (&config_modem_clear);
  861.     Cvar_RegisterVariable (&config_modem_init);
  862.     Cvar_RegisterVariable (&config_modem_hangup);
  863. #ifdef IDGODS
  864.     Cvar_RegisterVariable (&idgods);
  865. #endif
  866.  
  867.     Cmd_AddCommand ("slist", NET_Slist_f);
  868.     Cmd_AddCommand ("listen", NET_Listen_f);
  869.     Cmd_AddCommand ("maxplayers", MaxPlayers_f);
  870.     Cmd_AddCommand ("port", NET_Port_f);
  871.  
  872.     // initialize all the drivers
  873.     for (net_driverlevel=0 ; net_driverlevel<net_numdrivers ; net_driverlevel++)
  874.         {
  875.         controlSocket = net_drivers[net_driverlevel].Init();
  876.         if (controlSocket == -1)
  877.             continue;
  878.         net_drivers[net_driverlevel].initialized = true;
  879.         net_drivers[net_driverlevel].controlSock = controlSocket;
  880.         if (listening)
  881.             net_drivers[net_driverlevel].Listen (true);
  882.         }
  883.  
  884.     if (*my_ipx_address)
  885.         Con_DPrintf("IPX address %s\n", my_ipx_address);
  886.     if (*my_tcpip_address)
  887.         Con_DPrintf("TCP/IP address %s\n", my_tcpip_address);
  888. }
  889.  
  890. /*
  891. ====================
  892. NET_Shutdown
  893. ====================
  894. */
  895.  
  896. void        NET_Shutdown (void)
  897. {
  898.     qsocket_t    *sock;
  899.  
  900.     SetNetTime();
  901.  
  902.     for (sock = net_activeSockets; sock; sock = sock->next)
  903.         NET_Close(sock);
  904.  
  905. //
  906. // shutdown the drivers
  907. //
  908.     for (net_driverlevel = 0; net_driverlevel < net_numdrivers; net_driverlevel++)
  909.     {
  910.         if (net_drivers[net_driverlevel].initialized == true)
  911.         {
  912.             net_drivers[net_driverlevel].Shutdown ();
  913.             net_drivers[net_driverlevel].initialized = false;
  914.         }
  915.     }
  916.  
  917.     if (vcrFile != -1)
  918.     {
  919.         Con_Printf ("Closing vcrfile.\n");
  920.         Sys_FileClose(vcrFile);
  921.     }
  922. }
  923.  
  924.  
  925. static PollProcedure *pollProcedureList = NULL;
  926.  
  927. void NET_Poll(void)
  928. {
  929.     PollProcedure *pp;
  930.     qboolean    useModem;
  931.  
  932.     if (!configRestored)
  933.     {
  934.         if (serialAvailable)
  935.         {
  936.             if (config_com_modem.value == 1.0)
  937.                 useModem = true;
  938.             else
  939.                 useModem = false;
  940.             SetComPortConfig (0, (int)config_com_port.value, (int)config_com_irq.value, (int)config_com_baud.value, useModem);
  941.             SetModemConfig (0, config_modem_dialtype.string, config_modem_clear.string, config_modem_init.string, config_modem_hangup.string);
  942.         }
  943.         configRestored = true;
  944.     }
  945.  
  946.     SetNetTime();
  947.  
  948.     for (pp = pollProcedureList; pp; pp = pp->next)
  949.     {
  950.         if (pp->nextTime > net_time)
  951.             break;
  952.         pollProcedureList = pp->next;
  953.         pp->procedure(pp->arg);
  954.     }
  955. }
  956.  
  957.  
  958. void SchedulePollProcedure(PollProcedure *proc, double timeOffset)
  959. {
  960.     PollProcedure *pp, *prev;
  961.  
  962.     proc->nextTime = Sys_FloatTime() + timeOffset;
  963.     for (pp = pollProcedureList, prev = NULL; pp; pp = pp->next)
  964.     {
  965.         if (pp->nextTime >= proc->nextTime)
  966.             break;
  967.         prev = pp;
  968.     }
  969.  
  970.     if (prev == NULL)
  971.     {
  972.         proc->next = pollProcedureList;
  973.         pollProcedureList = proc;
  974.         return;
  975.     }
  976.  
  977.     proc->next = pp;
  978.     prev->next = proc;
  979. }
  980.  
  981.  
  982. #ifdef IDGODS
  983. #define IDNET    0xc0f62800
  984.  
  985. qboolean IsID(struct qsockaddr *addr)
  986. {
  987.     if (idgods.value == 0.0)
  988.         return false;
  989.  
  990.     if (addr->sa_family != 2)
  991.         return false;
  992.  
  993.     if ((BigLong(*(int *)&addr->sa_data[2]) & 0xffffff00) == IDNET)
  994.         return true;
  995.     return false;
  996. }
  997. #endif
  998.